home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
printing
/
rlpr-1.000
/
rlpr-1
/
rlpr-1.13
/
rlpr-net.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-30
|
8KB
|
223 lines
/* filename: rlpr-net.c
* project: rlpr
* author: meem -- meem@sherilyn.wustl.edu
* version: $Id: rlpr-net.c,v 1.11 1996/07/01 01:11:33 meem Exp $
* contents: network-related parts of rlpr (all the socket-based functions)
*
* Time-stamp: <1996/06/30 20:35 -- meem@sherilyn>
*/
/* copyright (c) 1996 meem, meem@gnu.ai.mit.edu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <sys/types.h>
#include <netinet/in.h> /* struct socketaddr_in definition */
#include <sys/socket.h> /* all the different socket types */
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h> /* network-specific functions here */
#include <stdio.h>
#include <string.h>
#include <sys/time.h> /* for timeval in select() calls */
#include <unistd.h> /* for unlink(), etc */
#include <errno.h>
#include "rlpr-common.h"
#include "rlpr-net.h"
void open_connection(void) {
struct sockaddr_in sin; /* socket struct with system info */
struct sockaddr_in sin_local; /* to bind a socket to a number */
struct hostent *hp; /* ptr to struct given by gethostbyname() */
int i, on; /* scrap variables */
/* zero out structs to get the unused part zeroed */
memset(&sin, 0, sizeof(sin));
memset(&sin_local, 0, sizeof(sin_local));
/* obtain a socket descriptor */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* 0 == auto proto config */
rlpr_fatal("socket: %s", ERRNO);
/* here if we're setuid root we can just bind to the right port
immediately and be done with it. otherwise we need to use a
proxy. if the proxy variable isn't set we assume they have it
installed setuid root. */
if (!*opts_.proxyhost) {
if (!(hp = gethostbyname(local_hostname)))
rlpr_fatal("hostname \"%s\" does not seem to exist!", local_hostname);
sin_local.sin_family = AF_INET;
memcpy(&sin_local.sin_addr, hp->h_addr, hp->h_length);
for (i = LO_LPD_FROM_NUM; i <= HI_LPD_FROM_NUM; i++) {
sin_local.sin_port = htons(i);
if (bind(sockfd, (struct sockaddr *) &sin_local, sizeof(sin_local)) >= 0)
break;
}
if (i > HI_LPD_FROM_NUM) /* didn't get a port */
if (errno == EACCES)
rlpr_fatal("bind to privileged port failed: "
"read rlpr(1) on using a proxyhost");
else rlpr_fatal("bind to ports %i-%i: %s",
LO_LPD_FROM_NUM, HI_LPD_FROM_NUM, ERRNO);
}
/* either we're connecting to the proxy or the real host */
if (!*opts_.proxyhost) /* USE PRINTHOST */ {
if (!(hp = gethostbyname(opts_.printhost)))
rlpr_fatal("hostname \"%s\" does not seem to exist!", opts_.printhost);
sin.sin_port = htons(LPD_TO_NUM); /* put it in network byte order */
} else /* USE PROXY */ {
if (!(hp = gethostbyname(opts_.proxyhost)))
rlpr_fatal("hostname \"%s\" does not seem to exist!", opts_.proxyhost);
sin.sin_port = htons(RLPRD_TO_NUM); /* put it in network byte order */
}
/* fill in sin struct, and connect */
memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); /* already in nbo */
sin.sin_family = AF_INET;
if (connect(sockfd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
if (errno == ECONNREFUSED)
rlpr_fatal("connection to %s refused! are you sure the daemon is up?",
(*opts_.proxyhost) ? opts_.proxyhost : opts_.printhost);
else rlpr_fatal("connect: %s", ERRNO);
if (*opts_.proxyhost) { /* if proxy, send out final destination */
if (write(sockfd, opts_.printhost, strlen(opts_.printhost)) < 0)
rlpr_fatal("write to rlprd: %s", ERRNO);
if (write(sockfd, "\n", 1) < 0)
rlpr_fatal("newline write to rlprd: %s", ERRNO);
}
}
void close_connection(void) {
if (close(sockfd) < 0)
rlpr_fatal("close: %s", ERRNO);
}
void recv_job_req(void) {
char buf[BUFSIZ]; /* should be more precise here */
sprintf(buf, "%c%s\n", RECVJ, opts_.printer);
if (write(sockfd, buf, strlen(buf)) < 0)
rlpr_fatal("write in recv_job_req: %s", ERRNO);
if (read(sockfd, buf, 1) < 0) /* check acknolwedgement */
rlpr_fatal("read in recv_job_req: %s", ERRNO);
else if (*buf)
rlpr_fatal("unable to queue job: maybe printer is down or doesn't exist");
}
void send_cf(int cfd, char *cfname) {
char buf[BUFSIZ];
int count;
char ack[1]; /* acknowledgement byte */
if (lseek(cfd, 0, SEEK_SET) < 0)
rlpr_fatal("lseek on control file: %s", ERRNO);
sprintf(buf, "%c%lu %s\n", RECVCF, filesz(cfd), cfname);
if (write(sockfd, buf, strlen(buf)) < 0)
rlpr_fatal("write in send_cf: %s", ERRNO);
if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
rlpr_fatal("read in send_cf: %s", ERRNO);
if (*ack) rlpr_fatal("server did not acknowledge client in send_cf");
while ((count = read(cfd, buf, BUFSIZ)) > 0) {
if (write(sockfd, buf, count) < 0)
rlpr_fatal("in sending control file to client: %s", ERRNO);
}
if (!count) {
if (write(sockfd, "\0", 1) < 0)
rlpr_fatal("write of acknowledgement in send_cf: %s", ERRNO);
}
else if (count < 0) rlpr_fatal("read on control file: %s", ERRNO);
if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
rlpr_fatal("read in send_cf: %s", ERRNO);
if (*ack) rlpr_fatal("server did not acknowledge client in send_cf");
}
void send_df(char *filename, char *dfname) {
char buf[BUFSIZ]; /* temporary buffer */
int count;
char ack[1]; /* acknowledgement byte */
int dfd; /* descriptor for datafile */
if (!filename) /* STDIN */ {
/* we need to make a dummy file to send, so that we know the size
* of stdin for machines that are not local. this is annoying but
* apparently required for most lpd's (even though RFC 1179 seems
* to say otherwise)
*/
filename = malloc(strlen(dfname) + strlen(TMPDIR) + 1);
sprintf(filename, "%s%s", TMPDIR, dfname);
if ((dfd = open(filename, O_RDWR|O_TRUNC|O_CREAT)) < 0)
rlpr_fatal("open on temporary file %s: %s",filename, ERRNO);
unlink(filename);
while ((count = read(STDIN_FILENO, buf, BUFSIZ)) > 0)
if (write(dfd, buf, count) < 0)
rlpr_fatal("writing stdin to temporary file %s: %s",
filename, ERRNO);
else if (count < 0)
rlpr_fatal("read on stdin: %s", ERRNO);
lseek(dfd, 0, SEEK_SET);
/* else have a filename from the commandline */
} else if ((dfd = open(filename, O_RDONLY)) < 0)
rlpr_fatal("cannot open %s: %s", filename, ERRNO);
/* COMMON */
sprintf(buf, "%c%lu %s\n", RECVDF, filesz(dfd), dfname);
if (write(sockfd, buf, strlen(buf)) < 0)
rlpr_fatal("write in send_df: %s", ERRNO);
if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
rlpr_fatal("read in send_df: %s", ERRNO);
if (*ack) rlpr_fatal("server did not acknowledge client in send_df1");
while ((count = read(dfd, buf, BUFSIZ)) > 0) {
if (write(sockfd, buf, count) < 0)
rlpr_fatal("in sending %s to client: %s",
filename ? filename : "stdin", ERRNO);
}
if (!count) {
if (write(sockfd, "\0", 1) < 0)
rlpr_fatal("write of acknowledgement in send_df: %s", ERRNO);
}
else if (count < 0) rlpr_fatal("read on data file: %s", ERRNO);
if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
rlpr_fatal("read in send_df: %s", ERRNO);
if (*ack) rlpr_fatal("server did not acknowledge client in send_df2");
}